#include "teststdafx.h"
#include "stdafx.h"
#include <gtest/gtest.h>

#include "Business/Customer.h"
#include "Service/MarketStorage.h"
#include "Business/ContractMatcher.h"
#include "Business/Policy/CallAuctionBusiness.h"
#include "Utils/StopWatch.h"

using namespace std;

class ContractMatcherTest : public testing::Test
{
protected:

	virtual void SetUp()
	{
	}

	virtual void TearDown()
	{

	}
	void foo();

	ContractMatcheres m_contractMatcheres;
};

TEST_F(ContractMatcherTest,CompleteTest)/*
void ContractMatcherTest::foo() /* */
{
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(18770,15);	matcher.Sell(18730,35); 
		matcher.Buy(18750,21);	matcher.Sell(18735,1); 
		matcher.Buy(18730,7);		matcher.Sell(18740,45); 
		matcher.Buy(18720,1);		matcher.Sell(18745,2);
		EXPECT_EQ(18735,matcher.Match());
//		EXPECT_EQ(2,matcher.GetOpenItemIndex());
//		matcher.Calc();
	}
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(18770,15);	matcher.Sell(18730,35); 
		matcher.Buy(18750,21);	matcher.Sell(18735,1); 
		matcher.Buy(18740,7);	matcher.Sell(18740,45); 
		matcher.Buy(18720,1);	matcher.Sell(18745,2);
		EXPECT_EQ(18740,matcher.Match());
// 		EXPECT_EQ(3,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(18770,15);	matcher.Sell(18730,35); 
		matcher.Buy(18750,21);	matcher.Sell(18735,1); 
		matcher.Buy(18740,70);	matcher.Sell(18740,45); 
		matcher.Buy(18720,1);	matcher.Sell(18745,2);
		EXPECT_EQ(18740,matcher.Match());
// 		EXPECT_EQ(3,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}	
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(18770,15);	matcher.Sell(18730,35); 
		matcher.Buy(18750,21);	matcher.Sell(18735,1); 
		matcher.Buy(18740,7);	matcher.Sell(18745,45); 
		matcher.Buy(18720,1);	matcher.Sell(18750,2);
		EXPECT_EQ(18745,matcher.Match());
// 		EXPECT_EQ(2,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(23975,1);	matcher.Sell(22585,1); 
		matcher.Buy(23970,2);	
		EXPECT_EQ(23975,matcher.Match());
// 		EXPECT_EQ(0,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(23975,1);	matcher.Sell(22585,1); 
									matcher.Sell(22590,2);	
		EXPECT_EQ(22585,matcher.Match());
// 		EXPECT_EQ(0,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}
	{
		ContractMatcher matcher(1,5);
		matcher.Buy(22585,1);	matcher.Sell(23975,1); 
		matcher.Buy(22590,1);	matcher.Sell(23970,1); 
		matcher.Buy(22595,1);	matcher.Sell(23965,1); 
		matcher.Buy(22600,1);	matcher.Sell(23960,1); 
		matcher.Buy(22605,1);	matcher.Sell(23955,1); 
		EXPECT_EQ(0,matcher.Match());
// 		EXPECT_EQ(-1,matcher.GetOpenItemIndex());
// 		matcher.Calc();
	}
}

TEST_F(ContractMatcherTest,Test)/*
void ContractMatcherTest::foo() /* */
{
	ContractMatcher matcher(1,5);
	matcher.Buy(19695,	1	); matcher.Sell(18000,	5 ); 
	matcher.Buy(18680,	1	); matcher.Sell(18045,	1  ); 
	matcher.Buy(18650,	1	); matcher.Sell(18300,	8  ); 
	matcher.Buy(18610,	1	); matcher.Sell(18350,	2  ); 
	matcher.Buy(18600,	1	); matcher.Sell(18400,	1  ); 
	matcher.Buy(18585,	2	); matcher.Sell(18430,	1  ); 
	matcher.Buy(18580,	1	); matcher.Sell(18440,	1  ); 
	matcher.Buy(18560,	1	); matcher.Sell(18470,	5  ); 
	matcher.Buy(18550,	2	); matcher.Sell(18475,	5  ); 
	matcher.Buy(18520,	1	); matcher.Sell(18480,	5  ); 
	matcher.Buy(18515,	1	); matcher.Sell(18490,	1  ); 
	matcher.Buy(18510,	1	); matcher.Sell(18495,	5  ); 
	matcher.Buy(18500,	15	); matcher.Sell(18500,	45); 
	matcher.Buy(18485,	2	); matcher.Sell(18515,	1  ); 
	matcher.Buy(18480,	1	); matcher.Sell(18520,	3  ); 
	matcher.Buy(18475,	2	); matcher.Sell(18560,	2  ); 
	matcher.Buy(18460,	1	); matcher.Sell(18575,	1  ); 
	matcher.Buy(18450,	6	); matcher.Sell(18600,	5  ); 
	matcher.Buy(18425,	1	); matcher.Sell(18625,	1  ); 
	matcher.Buy(18420,	1	); matcher.Sell(18640,	1  ); 
	matcher.Buy(18415,	7	); matcher.Sell(18650,	3  ); 
	matcher.Buy(18400,	28	); matcher.Sell(18660,	1  ); 
	matcher.Buy(18380,	3	); matcher.Sell(18680,	2  ); 
	matcher.Buy(18350,	2	); matcher.Sell(18700,	4  ); 
	matcher.Buy(18345,	10	); matcher.Sell(18750,	1  ); 
	matcher.Buy(18320,	45	); matcher.Sell(18760,	8  ); 
	matcher.Buy(18315,	2	); matcher.Sell(18780,	1  ); 
	matcher.Buy(18310,	2	); matcher.Sell(18790,	4  ); 
	matcher.Buy(18305,	11	); matcher.Sell(18820,	1  ); 
	matcher.Buy(18300,	25	); matcher.Sell(18870,	1  ); 
	matcher.Buy(18250,	1	); matcher.Sell(18900,	2  ); 
	matcher.Buy(18220,	10	); matcher.Sell(19000,	1  ); 
	matcher.Buy(18210,	15	); matcher.Sell(19100,	1  ); 
	matcher.Buy(18200,	7	); matcher.Sell(19120,	3  ); 
	matcher.Buy(18180,	3	); matcher.Sell(19300,	2  ); 
	matcher.Buy(18155,	3	); matcher.Sell(19590,	1  ); 
	matcher.Buy(18130,	1	); matcher.Sell(19695,	2  ); 
	matcher.Buy(18120,	10	);			 
	matcher.Buy(18110,	1	);			 
	matcher.Buy(18100,	5	);			 
	matcher.Buy(18060,	10	);			 
	matcher.Buy(18000,	7	);			 
	matcher.Buy(17950,	1	);			 
	matcher.Buy(17900,	2	);

	EXPECT_EQ(18480,matcher.Match());
	char buff[1024] = "";

	vector<OrderItem> const& buyOrderItems = matcher.GetBuyOrderItems();
	for (size_t i = 0; i < buyOrderItems.size(); ++i)
	{
		OrderItem const& item = buyOrderItems[i];
		ContractMatcher matcherTest = matcher;
		matcherTest.AddBuy(item.orderPrice,item.quantity);
		EXPECT_EQ(item.dealPrice,matcherTest.Match());
	}
	OrderItems const& sellOrderItems = matcher.GetSellOrderItems();
	for (size_t i = 0; i < sellOrderItems.size(); ++i)
	{
		OrderItem const& item = sellOrderItems[i];
		ContractMatcher matcherTest = matcher;
		matcherTest.AddSell(item.orderPrice,item.quantity);
		EXPECT_EQ(item.dealPrice,matcherTest.Match());
	}

}																	 

TEST_F(ContractMatcherTest,MajorTest)/*
void ContractMatcherTest::foo() /* */
{
	ContractMatcher matcher(0,5);
	matcher.Buy(19515,	4	);matcher.Sell(	17660,	11	);
	matcher.Buy(18880,	1	);matcher.Sell(	17700,	22	);
	matcher.Buy(18735,	13	);matcher.Sell(	17885,	40	);
	matcher.Buy(18590,	10	);matcher.Sell(	17975,	6	);
	matcher.Buy(18500,	1	);matcher.Sell(	17980,	10	);
	matcher.Buy(18495,	28	);matcher.Sell(	17990,	2	);
	matcher.Buy(18490,	4	);matcher.Sell(	17995,	1	);
	matcher.Buy(18480,	5	);matcher.Sell(	18000,	53	);
	matcher.Buy(18470,	1	);matcher.Sell(	18095,	5	);
	matcher.Buy(18465,	5	);matcher.Sell(	18100,	1	);
	matcher.Buy(18460,	1	);matcher.Sell(	18180,	30	);
	matcher.Buy(18455,	1	);matcher.Sell(	18200,	19	);
	matcher.Buy(18450,	2	);matcher.Sell(	18215,	2	);
	matcher.Buy(18440,	1	);matcher.Sell(	18230,	2	);
	matcher.Buy(18430,	7	);matcher.Sell(	18240,	1	);
	matcher.Buy(18425,	1	);matcher.Sell(	18250,	10	);
	matcher.Buy(18420,	9	);matcher.Sell(	18260,	25	);
	matcher.Buy(18410,	1	);matcher.Sell(	18270,	4	);
	matcher.Buy(18405,	1	);matcher.Sell(	18280,	52	);
	matcher.Buy(18400,	25	);matcher.Sell(	18290,	6	);
	matcher.Buy(18390,	1	);matcher.Sell(	18295,	2	);
	matcher.Buy(18380,	19	);matcher.Sell(	18300,	49	);
	matcher.Buy(18370,	11	);matcher.Sell(	18310,	1	);
	matcher.Buy(18365,	1	);matcher.Sell(	18320,	22	);
	matcher.Buy(18360,	12	);matcher.Sell(	18325,	6	);
	matcher.Buy(18350,	7	);matcher.Sell(	18330,	2	);
	matcher.Buy(18325,	4	);matcher.Sell(	18340,	2	);
	matcher.Buy(18320,	8	);matcher.Sell(	18345,	92	);
	matcher.Buy(18310,	47	);matcher.Sell(	18350,	22	);
	matcher.Buy(18305,	14	);matcher.Sell(	18360,	38	);
	matcher.Buy(18300,	217	);matcher.Sell(	18380,	87	);
	matcher.Buy(18285,	2	);matcher.Sell(	18385,	1	);
	matcher.Buy(18280,	8	);matcher.Sell(	18390,	5	);
	matcher.Buy(18275,	15	);matcher.Sell(	18395,	43	);
	matcher.Buy(18270,	41	);matcher.Sell(	18400,	203	);
	matcher.Buy(18265,	21	);matcher.Sell(	18405,	1	);
	matcher.Buy(18260,	30	);matcher.Sell(	18410,	4	);
	matcher.Buy(18255,	10	);matcher.Sell(	18415,	1	);
	matcher.Buy(18250,	150	);matcher.Sell(	18420,	2	);
	matcher.Buy(18245,	1	);matcher.Sell(	18425,	15	);
	matcher.Buy(18235,	51	);matcher.Sell(	18430,	2	);
	matcher.Buy(18230,	34	);matcher.Sell(	18440,	5	);
	matcher.Buy(18225,	11	);matcher.Sell(	18445,	10	);
	matcher.Buy(18220,	54	);matcher.Sell(	18450,	45	);
	matcher.Buy(18215,	59	);matcher.Sell(	18455,	1	);
	matcher.Buy(18210,	72	);matcher.Sell(	18460,	1	);
	matcher.Buy(18205,	211	);matcher.Sell(	18470,	10	);
	matcher.Buy(18200,	183	);matcher.Sell(	18480,	40	);
	matcher.Buy(18195,	6	);matcher.Sell(	18485,	2	);
	matcher.Buy(18190,	3	);matcher.Sell(	18490,	44	);
	matcher.Buy(18180,	25	);matcher.Sell(	18495,	15	);
	matcher.Buy(18175,	3	);matcher.Sell(	18500,	80	);
	matcher.Buy(18170,	6	);matcher.Sell(	18505,	4	);
	matcher.Buy(18165,	7	);matcher.Sell(	18510,	12	);
	matcher.Buy(18160,	2	);matcher.Sell(	18515,	4	);
	matcher.Buy(18155,	1	);matcher.Sell(	18520,	15	);
	matcher.Buy(18150,	10	);matcher.Sell(	18525,	2	);
	matcher.Buy(18135,	1	);matcher.Sell(	18530,	52	);
	matcher.Buy(18130,	6	);matcher.Sell(	18535,	2	);
	matcher.Buy(18120,	32	);matcher.Sell(	18540,	3	);
	matcher.Buy(18115,	14	);matcher.Sell(	18550,	2	);
	matcher.Buy(18110,	9	);matcher.Sell(	18560,	43	);
	matcher.Buy(18105,	1	);matcher.Sell(	18570,	96	);
	matcher.Buy(18100,	31	);matcher.Sell(	18575,	1	);
	matcher.Buy(18090,	2	);matcher.Sell(	18580,	13	);
	matcher.Buy(18080,	2	);matcher.Sell(	18585,	1	);
	matcher.Buy(18075,	7	);matcher.Sell(	18590,	205	);
	matcher.Buy(18070,	12	);matcher.Sell(	18595,	3	);
	matcher.Buy(18065,	4	);matcher.Sell(	18600,	145	);
	matcher.Buy(18060,	3	);matcher.Sell(	18610,	5	);
	matcher.Buy(18055,	3	);matcher.Sell(	18620,	1	);
	matcher.Buy(18050,	18	);matcher.Sell(	18625,	4	);
	matcher.Buy(18030,	11	);matcher.Sell(	18630,	3	);
	matcher.Buy(18020,	113	);matcher.Sell(	18640,	3	);
	matcher.Buy(18015,	3	);matcher.Sell(	18645,	2	);
	matcher.Buy(18010,	17	);matcher.Sell(	18650,	21	);
	matcher.Buy(18005,	4	);matcher.Sell(	18660,	1	);
	matcher.Buy(18000,	33	);matcher.Sell(	18670,	2	);
	matcher.Buy(17935,	1	);matcher.Sell(	18680,	2	);
	matcher.Buy(17925,	1	);matcher.Sell(	18690,	51	);
	matcher.Buy(17920,	1	);matcher.Sell(	18700,	42	);
	matcher.Buy(17905,	1	);matcher.Sell(	18710,	9	);
	matcher.Buy(17900,	2	);matcher.Sell(	18715,	28	);
	matcher.Buy(17880,	2	);matcher.Sell(	18750,	15	);
	matcher.Buy(17810,	1	);matcher.Sell(	18770,	1	);
	matcher.Buy(17800,	1	);matcher.Sell(	18780,	11	);
	matcher.Buy(17740,	1	);matcher.Sell(	18790,	13	);
	matcher.Buy(17720,	2	);matcher.Sell(	18800,	3	);
	matcher.Buy(17715,	1	);matcher.Sell(	18815,	4	);
	matcher.Buy(17700,	2	);matcher.Sell(	18845,	2	);
	matcher.Buy(17680,	1	);matcher.Sell(	18850,	1	);
	matcher.Buy(17660,	1	);matcher.Sell(	18860,	1	);
							matcher.Sell(	18870,	11	);
							matcher.Sell(	18875,	1	);
							matcher.Sell(	18890,	1	);
							matcher.Sell(	18900,	1	);
							matcher.Sell(	18905,	2	);
							matcher.Sell(	18940,	3	);
							matcher.Sell(	18980,	10	);
							matcher.Sell(	18985,	1	);
							matcher.Sell(	18995,	1	);
							matcher.Sell(	19000,	2	);
							matcher.Sell(	19060,	30	);
							matcher.Sell(	19065,	2	);
							matcher.Sell(	19100,	1	);
							matcher.Sell(	19200,	1	);
							matcher.Sell(	19210,	1	);
							matcher.Sell(	19240,	36	);
							matcher.Sell(	19250,	1	);
							matcher.Sell(	19390,	10	);
							matcher.Sell(	19400,	1	);
							matcher.Sell(	19440,	2	);
							matcher.Sell(	19450,	17	);
							matcher.Sell(	19480,	1	);
							matcher.Sell(	19490,	20	);
							matcher.Sell(	19500,	202	);

	DWORD time = 0;
	{
		StopWatch stopWatch(time);
		for (int i = 0; i < 100; ++i)
		{
			matcher.Match();
		}
		
	}
	cout << "performance:" << time << endl;
	EXPECT_EQ(18300,matcher.Match());
/*
	char buff[1024] = "";
 	vector<OrderItem> const& buyOrderItems = matcher.GetBuys();
	for (size_t i = 0; i < buyOrderItems.size(); ++i)
	{
		OrderItem const& item = buyOrderItems[i];
		ContractMatcher matcherTest = matcher;
		matcherTest.AddBuy(item.orderPrice,item.quantity);
		EXPECT_EQ(item.dealPrice,matcherTest.Match());
	}
 	vector<OrderItem> const& sellOrderItems = matcher.GetSells();
 	for (size_t i = 0; i < sellOrderItems.size(); ++i)
	{
		OrderItem const& item = sellOrderItems[i];
		ContractMatcher matcherTest = matcher;
		matcherTest.AddSell(item.orderPrice,item.quantity);
		EXPECT_EQ(item.dealPrice,matcherTest.Match());
	}
*/
}																	 
namespace {															 
	PendingMarket CF(int p, int q,Direction::TYPE d)			 
	{																 
		PendingMarket pm;											 
		pm.contract = 1;											 
		pm.direction = d;											 
		pm.price = p;												 
		pm.quantity = q;											 
		return pm;													 
	}																 
	PendingMarket CFB(int p,int q)									 
	{
		return CF(p,q,Direction::BUY);
	}
	PendingMarket CFS(int p,int q)
	{
		return CF(p,q,Direction::SELL);
	}

	PendingMarket CN(int p, int q,Direction::TYPE d)
	{
		PendingMarket pm;
		pm.contract = 0;
		pm.direction = d;
		pm.price = p;
		pm.quantity = q;
		return pm;
	}
	PendingMarket CNB(int p,int q)
	{
		return CN(p,q,Direction::BUY);
	}
	PendingMarket CNS(int p,int q)
	{
		return CN(p,q,Direction::SELL);
	}
}

TEST_F(ContractMatcherTest,FreezeAmountTest)/*
void ContractMatcherTest::foo() /* */
{
	ArbitrageContracts contracts(0,1);
	Band bearish(200,250,MORE_LOWER);
	Band bullish(140,100,MORE_UPPER);
	CallAuctionArgument argument(contracts,1,bearish,bullish,20000,20000,false,5,5);
	CallAuctionCalculater calculater(m_contractMatcheres,argument,5);
	Margins margins;
	margins.Add(Margin("",0.1));
	Variety variety0("zn1006",5,5);
	variety0.SetMargins(margins);
	Prices prices;

	Market market0(0,variety0,0,0,prices,prices,0,0,0);
	Market market1(1,variety0,0,0,prices,prices,0,0,0);

	MarketStorage storage;
	storage.Save(market0);
	storage.Save(market1);

	EXPECT_DOUBLE_EQ(20000,calculater.GetFreezeAmount(storage));
}

TEST_F(ContractMatcherTest,CalculaterTest)/*
void ContractMatcherTest::foo() /* */
{
	ArbitrageContracts contracts(0,1);
	Band bearish(200,250,MORE_LOWER);
	Band bullish(140,100,MORE_UPPER);
	CallAuctionArgument argument(contracts,20,bearish,bullish,20000,20000,false,5,5);
	CallAuctionCalculater calculater(m_contractMatcheres,argument,5);

	calculater.Update(CFB(19695,	1	)); calculater.Update(CFS(18000,	5 )); 
	calculater.Update(CFB(18680,	1	)); calculater.Update(CFS(18045,	1  )); 
	calculater.Update(CFB(18650,	1	)); calculater.Update(CFS(18300,	8  )); 
	calculater.Update(CFB(18610,	1	)); calculater.Update(CFS(18350,	2  )); 
	calculater.Update(CFB(18600,	1	)); calculater.Update(CFS(18400,	1  )); 
	calculater.Update(CFB(18585,	2	)); calculater.Update(CFS(18430,	1  )); 
	calculater.Update(CFB(18580,	1	)); calculater.Update(CFS(18440,	1  )); 
	calculater.Update(CFB(18560,	1	)); calculater.Update(CFS(18470,	5  )); 
	calculater.Update(CFB(18550,	2	)); calculater.Update(CFS(18475,	5  )); 
	calculater.Update(CFB(18520,	1	)); calculater.Update(CFS(18480,	5  )); 
	calculater.Update(CFB(18515,	1	)); calculater.Update(CFS(18490,	1  )); 
	calculater.Update(CFB(18510,	1	)); calculater.Update(CFS(18495,	5  )); 
	calculater.Update(CFB(18500,	15	)); calculater.Update(CFS(18500,	45)); 
	calculater.Update(CFB(18485,	2	)); calculater.Update(CFS(18515,	1  )); 
	calculater.Update(CFB(18480,	1	)); calculater.Update(CFS(18520,	3  )); 
	calculater.Update(CFB(18475,	2	)); calculater.Update(CFS(18560,	2  )); 
	calculater.Update(CFB(18460,	1	)); calculater.Update(CFS(18575,	1  )); 
	calculater.Update(CFB(18450,	6	)); calculater.Update(CFS(18600,	5  )); 
	calculater.Update(CFB(18425,	1	)); calculater.Update(CFS(18625,	1  )); 
	calculater.Update(CFB(18420,	1	)); calculater.Update(CFS(18640,	1  )); 
	calculater.Update(CFB(18415,	7	)); calculater.Update(CFS(18650,	3  )); 
	calculater.Update(CFB(18400,	28	)); calculater.Update(CFS(18660,	1  )); 
	calculater.Update(CFB(18380,	3	)); calculater.Update(CFS(18680,	2  )); 
	calculater.Update(CFB(18350,	2	)); calculater.Update(CFS(18700,	4  )); 
	calculater.Update(CFB(18345,	10	)); calculater.Update(CFS(18750,	1  )); 
	calculater.Update(CFB(18320,	45	)); calculater.Update(CFS(18760,	8  )); 
	calculater.Update(CFB(18315,	2	)); calculater.Update(CFS(18780,	1  )); 
	calculater.Update(CFB(18310,	2	)); calculater.Update(CFS(18790,	4  )); 
	calculater.Update(CFB(18305,	11	)); calculater.Update(CFS(18820,	1  )); 
	calculater.Update(CFB(18300,	25	)); calculater.Update(CFS(18870,	1  )); 
	calculater.Update(CFB(18250,	1	)); calculater.Update(CFS(18900,	2  )); 
	calculater.Update(CFB(18220,	10	)); calculater.Update(CFS(19000,	1  )); 
	calculater.Update(CFB(18210,	15	)); calculater.Update(CFS(19100,	1  )); 
	calculater.Update(CFB(18200,	7	)); calculater.Update(CFS(19120,	3  )); 
	calculater.Update(CFB(18180,	3	)); calculater.Update(CFS(19300,	2  )); 
	calculater.Update(CFB(18155,	3	)); calculater.Update(CFS(19590,	1  )); 
	calculater.Update(CFB(18130,	1	)); calculater.Update(CFS(19695,	2  )); 
	calculater.Update(CFB(18120,	10	));			 
	calculater.Update(CFB(18110,	1	));			 
	calculater.Update(CFB(18100,	5	));			 
	calculater.Update(CFB(18060,	10	));			 
	calculater.Update(CFB(18000,	7	));			 
	calculater.Update(CFB(17950,	1	));			 
	calculater.Update(CFB(17900,	2	));

	calculater.Update(CNB(19515,	4	));calculater.Update(CNS(	17660,	11	));
	calculater.Update(CNB(18880,	1	));calculater.Update(CNS(	17700,	22	));
	calculater.Update(CNB(18735,	13	));calculater.Update(CNS(	17885,	40	));
	calculater.Update(CNB(18590,	10	));calculater.Update(CNS(	17975,	6	));
	calculater.Update(CNB(18500,	1	));calculater.Update(CNS(	17980,	10	));
	calculater.Update(CNB(18495,	28	));calculater.Update(CNS(	17990,	2	));
	calculater.Update(CNB(18490,	4	));calculater.Update(CNS(	17995,	1	));
	calculater.Update(CNB(18480,	5	));calculater.Update(CNS(	18000,	53	));
	calculater.Update(CNB(18470,	1	));calculater.Update(CNS(	18095,	5	));
	calculater.Update(CNB(18465,	5	));calculater.Update(CNS(	18100,	1	));
	calculater.Update(CNB(18460,	1	));calculater.Update(CNS(	18180,	30	));
	calculater.Update(CNB(18455,	1	));calculater.Update(CNS(	18200,	19	));
	calculater.Update(CNB(18450,	2	));calculater.Update(CNS(	18215,	2	));
	calculater.Update(CNB(18440,	1	));calculater.Update(CNS(	18230,	2	));
	calculater.Update(CNB(18430,	7	));calculater.Update(CNS(	18240,	1	));
	calculater.Update(CNB(18425,	1	));calculater.Update(CNS(	18250,	10	));
	calculater.Update(CNB(18420,	9	));calculater.Update(CNS(	18260,	25	));
	calculater.Update(CNB(18410,	1	));calculater.Update(CNS(	18270,	4	));
	calculater.Update(CNB(18405,	1	));calculater.Update(CNS(	18280,	52	));
	calculater.Update(CNB(18400,	25	));calculater.Update(CNS(	18290,	6	));
	calculater.Update(CNB(18390,	1	));calculater.Update(CNS(	18295,	2	));
	calculater.Update(CNB(18380,	19	));calculater.Update(CNS(	18300,	49	));
	calculater.Update(CNB(18370,	11	));calculater.Update(CNS(	18310,	1	));
	calculater.Update(CNB(18365,	1	));calculater.Update(CNS(	18320,	22	));
	calculater.Update(CNB(18360,	12	));calculater.Update(CNS(	18325,	6	));
	calculater.Update(CNB(18350,	7	));calculater.Update(CNS(	18330,	2	));
	calculater.Update(CNB(18325,	4	));calculater.Update(CNS(	18340,	2	));
	calculater.Update(CNB(18320,	8	));calculater.Update(CNS(	18345,	92	));
	calculater.Update(CNB(18310,	47	));calculater.Update(CNS(	18350,	22	));
	calculater.Update(CNB(18305,	14	));calculater.Update(CNS(	18360,	38	));
	calculater.Update(CNB(18300,	217	));calculater.Update(CNS(	18380,	87	));
	calculater.Update(CNB(18285,	2	));calculater.Update(CNS(	18385,	1	));
	calculater.Update(CNB(18280,	8	));calculater.Update(CNS(	18390,	5	));
	calculater.Update(CNB(18275,	15	));calculater.Update(CNS(	18395,	43	));
	calculater.Update(CNB(18270,	41	));calculater.Update(CNS(	18400,	203	));
	calculater.Update(CNB(18265,	21	));calculater.Update(CNS(	18405,	1	));
	calculater.Update(CNB(18260,	30	));calculater.Update(CNS(	18410,	4	));
	calculater.Update(CNB(18255,	10	));calculater.Update(CNS(	18415,	1	));
	calculater.Update(CNB(18250,	150	));calculater.Update(CNS(	18420,	2	));
	calculater.Update(CNB(18245,	1	));calculater.Update(CNS(	18425,	15	));
	calculater.Update(CNB(18235,	51	));calculater.Update(CNS(	18430,	2	));
	calculater.Update(CNB(18230,	34	));calculater.Update(CNS(	18440,	5	));
	calculater.Update(CNB(18225,	11	));calculater.Update(CNS(	18445,	10	));
	calculater.Update(CNB(18220,	54	));calculater.Update(CNS(	18450,	45	));
	calculater.Update(CNB(18215,	59	));calculater.Update(CNS(	18455,	1	));
	calculater.Update(CNB(18210,	72	));calculater.Update(CNS(	18460,	1	));
	calculater.Update(CNB(18205,	211	));calculater.Update(CNS(	18470,	10	));
	calculater.Update(CNB(18200,	183	));calculater.Update(CNS(	18480,	40	));
	calculater.Update(CNB(18195,	6	));calculater.Update(CNS(	18485,	2	));
	calculater.Update(CNB(18190,	3	));calculater.Update(CNS(	18490,	44	));
	calculater.Update(CNB(18180,	25	));calculater.Update(CNS(	18495,	15	));
	calculater.Update(CNB(18175,	3	));calculater.Update(CNS(	18500,	80	));
	calculater.Update(CNB(18170,	6	));calculater.Update(CNS(	18505,	4	));
	calculater.Update(CNB(18165,	7	));calculater.Update(CNS(	18510,	12	));
	calculater.Update(CNB(18160,	2	));calculater.Update(CNS(	18515,	4	));
	calculater.Update(CNB(18155,	1	));calculater.Update(CNS(	18520,	15	));
	calculater.Update(CNB(18150,	10	));calculater.Update(CNS(	18525,	2	));
	calculater.Update(CNB(18135,	1	));calculater.Update(CNS(	18530,	52	));
	calculater.Update(CNB(18130,	6	));calculater.Update(CNS(	18535,	2	));
	calculater.Update(CNB(18120,	32	));calculater.Update(CNS(	18540,	3	));
	calculater.Update(CNB(18115,	14	));calculater.Update(CNS(	18550,	2	));
	calculater.Update(CNB(18110,	9	));calculater.Update(CNS(	18560,	43	));
	calculater.Update(CNB(18105,	1	));calculater.Update(CNS(	18570,	96	));
	calculater.Update(CNB(18100,	31	));calculater.Update(CNS(	18575,	1	));
	calculater.Update(CNB(18090,	2	));calculater.Update(CNS(	18580,	13	));
	calculater.Update(CNB(18080,	2	));calculater.Update(CNS(	18585,	1	));
	calculater.Update(CNB(18075,	7	));calculater.Update(CNS(	18590,	205	));
	calculater.Update(CNB(18070,	12	));calculater.Update(CNS(	18595,	3	));
	calculater.Update(CNB(18065,	4	));calculater.Update(CNS(	18600,	145	));
	calculater.Update(CNB(18060,	3	));calculater.Update(CNS(	18610,	5	));
	calculater.Update(CNB(18055,	3	));calculater.Update(CNS(	18620,	1	));
	calculater.Update(CNB(18050,	18	));calculater.Update(CNS(	18625,	4	));
	calculater.Update(CNB(18030,	11	));calculater.Update(CNS(	18630,	3	));
	calculater.Update(CNB(18020,	113	));calculater.Update(CNS(	18640,	3	));
	calculater.Update(CNB(18015,	3	));calculater.Update(CNS(	18645,	2	));
	calculater.Update(CNB(18010,	17	));calculater.Update(CNS(	18650,	21	));
	calculater.Update(CNB(18005,	4	));calculater.Update(CNS(	18660,	1	));
	calculater.Update(CNB(18000,	33	));calculater.Update(CNS(	18670,	2	));
	calculater.Update(CNB(17935,	1	));calculater.Update(CNS(	18680,	2	));
	calculater.Update(CNB(17925,	1	));calculater.Update(CNS(	18690,	51	));
	calculater.Update(CNB(17920,	1	));calculater.Update(CNS(	18700,	42	));
	calculater.Update(CNB(17905,	1	));calculater.Update(CNS(	18710,	9	));
	calculater.Update(CNB(17900,	2	));calculater.Update(CNS(	18715,	28	));
	calculater.Update(CNB(17880,	2	));calculater.Update(CNS(	18750,	15	));
	calculater.Update(CNB(17810,	1	));calculater.Update(CNS(	18770,	1	));
	calculater.Update(CNB(17800,	1	));calculater.Update(CNS(	18780,	11	));
	calculater.Update(CNB(17740,	1	));calculater.Update(CNS(	18790,	13	));
	calculater.Update(CNB(17720,	2	));calculater.Update(CNS(	18800,	3	));
	calculater.Update(CNB(17715,	1	));calculater.Update(CNS(	18815,	4	));
	calculater.Update(CNB(17700,	2	));calculater.Update(CNS(	18845,	2	));
	calculater.Update(CNB(17680,	1	));calculater.Update(CNS(	18850,	1	));
	calculater.Update(CNB(17660,	1	));calculater.Update(CNS(	18860,	1	));
	calculater.Update(CNS(	18870,	11	));
	calculater.Update(CNS(	18875,	1	));
	calculater.Update(CNS(	18890,	1	));
	calculater.Update(CNS(	18900,	1	));
	calculater.Update(CNS(	18905,	2	));
	calculater.Update(CNS(	18940,	3	));
	calculater.Update(CNS(	18980,	10	));
	calculater.Update(CNS(	18985,	1	));
	calculater.Update(CNS(	18995,	1	));
	calculater.Update(CNS(	19000,	2	));
	calculater.Update(CNS(	19060,	30	));
	calculater.Update(CNS(	19065,	2	));
	calculater.Update(CNS(	19100,	1	));
	calculater.Update(CNS(	19200,	1	));
	calculater.Update(CNS(	19210,	1	));
	calculater.Update(CNS(	19240,	36	));
	calculater.Update(CNS(	19250,	1	));
	calculater.Update(CNS(	19390,	10	));
	calculater.Update(CNS(	19400,	1	));
	calculater.Update(CNS(	19440,	2	));
	calculater.Update(CNS(	19450,	17	));
	calculater.Update(CNS(	19480,	1	));
	calculater.Update(CNS(	19490,	20	));
	calculater.Update(CNS(	19500,	202	));
	calculater.Match();

	MarketStorage marketStorage;
	Margins margins;
	margins.Add(Margin("",0.1));
	Variety variety0("zn1006",5,5);
	variety0.SetMargins(margins);
	Prices prices;

	Market market0(0,variety0,0,0,prices,prices,0,0,0);
	Market market1(1,variety0,0,0,prices,prices,0,0,0);

	MarketStorage storage;
	marketStorage.Save(market0);
	marketStorage.Save(market1);	
	char buff[1024] = "";
	{
		CalculateResult result = calculater.CalcBullish(900000,marketStorage);
		cout << "bullish" << endl;
		sprintf_s(buff,"[%d][%d][%d][%d][%d][%.2f]",result.quantity,result.fartherOrderPrice,result.fartherDealPrice,
			result.nearbyOrderPrice,result.nearbyDealPrice,result.profit);
		cout << buff << endl;
	}
	{
		CalculateResult result = calculater.CalcBearish(900000,marketStorage);
		cout << "bearish" << endl;
		sprintf_s(buff,"[%d][%d][%d][%d][%d][%.2f]",result.quantity,result.fartherOrderPrice,result.fartherDealPrice,
			result.nearbyOrderPrice,result.nearbyDealPrice,result.profit);
		cout << buff << endl;
	}
}

bool operator==(MatchItem const& l, MatchItem const& r)
{
	return l.buyPrice == r.buyPrice && l.buyQuantity == r.buyQuantity &&
		   l.currentPrice == r.currentPrice && l.sellPrice == r.sellPrice &&
		   l.sellQuantity == r.sellQuantity && l.matched == r.matched;
}

ostream& operator<<(ostream& os,MatchItem const& item)
{
	os << item.buyPrice << "\t" << item.currentPrice << "\t" << item.sellPrice << "\t" << item.buyQuantity;
	os << "\t" << item.sellQuantity << "\t" << item.matched;
	return os;
}

ostream& operator<<(ostream& os,MatchItems const& items)
{
	for (size_t i = 0; i < items.size(); ++i)
	{
		MatchItem const& item = items[i];
		os << item << " | ";
	}
	return os;
}

TEST_F(ContractMatcherTest, MatchTest)/*
void ContractMatcherTest::foo() /* */
{
	{
        ContractMatcher matcher(0,5);
        matcher.Buy(18000,1).Sell(19100,1);
        matcher.Buy(18010,1).Sell(19090,1);
        EXPECT_EQ(0,matcher.Match());
	}   
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(19100,1).Sell(18000,1);
        matcher.Buy(19090,2).Sell(18010,1);
        EXPECT_EQ(19090,matcher.Match());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(19100,1).Sell(18000,1);
        matcher.Buy(19090,1).Sell(18010,2);
        EXPECT_EQ(18010,matcher.Match());
	}   
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(19100,1).Sell(18000,1);
        matcher.Buy(19090,1);
        EXPECT_EQ(19100,matcher.Match());
	}   
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(19100,1).Sell(18000,1);
        matcher.Sell(18010,1);
        EXPECT_EQ(18000,matcher.Match());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(19105,1).Sell(18000,1);
        EXPECT_EQ(18550,matcher.Match());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,1);
        matcher.Buy(18730,7).Sell(18740,45);
        matcher.Buy(18720,1).Sell(18745,2);
        EXPECT_EQ(18735,matcher.Match());
        // cu1006 2010-04-07
		ContractMatcher matcher2(0,5);
        matcher2.Buy(66220,1).Sell(63000,23);
        matcher2.Buy(63200,1).Sell(63050,1);
        matcher2.Buy(63100,1);
        matcher2.Buy(63070,20);
        matcher2.Buy(63060,1);
        matcher2.Buy(63050,24);
        matcher2.Buy(63030,15);
        EXPECT_EQ(63060,matcher2.Match());
	}
}

TEST_F(ContractMatcherTest, AllItemsTest)/*
void ContractMatcherTest::foo() /* */
{
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,1); 
        matcher.Buy(18730,7).Sell(18740,45); 
        matcher.Buy(18720,1).Sell(18745,2);
        matcher.Match();
		matcher.GenerateItems();
        MatchItems expected;
        expected.push_back(MatchItem(18770,18730,18730,15,35,15));
        expected.push_back(MatchItem(18750,18750,18730,21,20,35));
        expected.push_back(MatchItem(18750,18735,18735,1,1,36));
        expected.push_back(MatchItem(18730,18735,18740,7,45,36));
        expected.push_back(MatchItem(18720,18735,18745,1,2,36));
        EXPECT_EQ(expected,matcher.GetAllItems());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,1);
        matcher.Buy(18730,7).Sell(18740,45);
        matcher.Buy(18720,1);
        matcher.Match();
		matcher.GenerateItems();
		MatchItems expected;
        expected.push_back(MatchItem(18770,18730,18730,15,35,15));
        expected.push_back(MatchItem(18750,18750,18730,21,20,35));
        expected.push_back(MatchItem(18750,18735,18735,1,1,36));
        expected.push_back(MatchItem(18730,18735,18740,7,45,36));
        expected.push_back(MatchItem(18720,18735,0,1,0,36));
        EXPECT_EQ(expected,matcher.GetAllItems());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,1);
        matcher.Buy(18730,7).Sell(18740,45); 
        matcher.Sell(18745,2);
        matcher.Match();
		matcher.GenerateItems();
		MatchItems expected;
        expected.push_back(MatchItem(18770,18730,18730,15,35,15));
        expected.push_back(MatchItem(18750,18750,18730,21,20,35));
        expected.push_back(MatchItem(18750,18735,18735,1,1,36));
        expected.push_back(MatchItem(18730,18735,18740,7,45,36));
        expected.push_back(MatchItem(0,18735,18745,0,2,36));
        EXPECT_EQ(expected,matcher.GetAllItems());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,1); 
        matcher.Match();
		matcher.GenerateItems();
		MatchItems expected;
        expected.push_back(MatchItem(18770,18730,18730,15,35,15));
        expected.push_back(MatchItem(18750,18750,18730,21,20,35));
        expected.push_back(MatchItem(18750,18740,18735,1,1,36));
        EXPECT_EQ(expected,matcher.GetAllItems());
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18770,15).Sell(18730,35);
        matcher.Buy(18750,21).Sell(18735,2); 
        matcher.Buy(18730,7).Sell(18740,45); 
        matcher.Buy(18720,1).Sell(18745,2);
        matcher.Match();
		matcher.GenerateItems();
		MatchItems expected;
        expected.push_back(MatchItem(18770,18730,18730,15,35,15));
        expected.push_back(MatchItem(18750,18750,18730,21,20,35));
        expected.push_back(MatchItem(18750,18735,18735,1,2,36));
        expected.push_back(MatchItem(18730,18735,18735,7,1,36));
        expected.push_back(MatchItem(18720,18735,18740,1,45,36));
        expected.push_back(MatchItem(0,18735,18745,0,2,36));
        EXPECT_EQ(expected,matcher.GetAllItems());
	}
}

bool operator==(OrderItem const& l, OrderItem const& r)
{
	return l.dealPrice == r.dealPrice && l.orderPrice == r.orderPrice && l.quantity == r.quantity;
}

ostream& operator<<(ostream& os, OrderItem const& item)
{
	os << item.orderPrice << "\t" << item.dealPrice << "\t" << item.quantity;
	return os;
}

ostream& operator<<(ostream& os, OrderItems const& items)
{
	for (size_t i = 0; i < items.size(); ++i)
	{
		os << items[i] << "|";
	}
	return os;
}



TEST_F(ContractMatcherTest, ChanceTest)/*
void ContractMatcherTest::foo() /* */
{
	{
		ContractMatcher matcher(0,5);
		matcher.Buy(18780,15).Sell(18730,35);
		matcher.Buy(18770,2).Sell(18735,1);
		matcher.Sell(18740,45);
		matcher.Sell(18765,2);
		matcher.Sell(18790,2);
		matcher.Match();
		matcher.GenerateItems();

		OrderItems buyChance;
		buyChance.push_back(OrderItem(18730,18730,18));
		buyChance.push_back(OrderItem(18735,18735,19));
		buyChance.push_back(OrderItem(18740,18740,64));
		buyChance.push_back(OrderItem(18765,18765,66));
		//buyChance.push_back(OrderItem(18770,18770,66));
		buyChance.push_back(OrderItem(18775,18770,67));
		buyChance.push_back(OrderItem(18775,18775,68));
		//buyChance.push_back(OrderItem(18780,18780,68));
		buyChance.push_back(OrderItem(18785,18780,82));
		buyChance.push_back(OrderItem(18785,18785,83));
		buyChance.push_back(OrderItem(18790,18790,85));
		EXPECT_EQ(buyChance,matcher.GetBuyOrderItems());
	}
	{
		ContractMatcher matcher(0,5);
        
        matcher.Buy(18780,40).Sell(18730,35);
        matcher.Buy(18770,2).Sell(18735,1);
        matcher.Buy(18765,1).Sell(18750,2);
        matcher.Buy(18755,31);
        matcher.Buy(18745,2);
        matcher.Buy(18720,2);
        matcher.Buy(18710,2);
        matcher.Match();
		matcher.GenerateItems();
        OrderItems sellChance;
		sellChance.push_back(OrderItem(18780,18780,2));
		sellChance.push_back(OrderItem(18770,18770,4));
		sellChance.push_back(OrderItem(18765,18765,5));
		sellChance.push_back(OrderItem(18755,18755,36));
		//sellChance.push_back(OrderItem(18750,18755,36));
		sellChance.push_back(OrderItem(18745,18750,37));
		sellChance.push_back(OrderItem(18745,18745,40));
		//sellChance.push_back(OrderItem(18735,18745,40));
		sellChance.push_back(OrderItem(18730,18730,41));
		sellChance.push_back(OrderItem(18725,18730,75));
		sellChance.push_back(OrderItem(18725,18725,76));
		sellChance.push_back(OrderItem(18720,18720,78));
		sellChance.push_back(OrderItem(18710,18710,80));
        
        EXPECT_EQ(sellChance,matcher.GetSellOrderItems());
		OrderItems const& sellOrderItems = matcher.GetSellOrderItems();
		for (size_t i = 0; i < sellOrderItems.size(); ++i)
		{
			OrderItem const& item = sellOrderItems[i];
			ContractMatcher matcherTest = matcher;
			matcherTest.AddSell(item.orderPrice,item.quantity);
			EXPECT_EQ(item.dealPrice,matcherTest.Match());
		}
	}
	{
		ContractMatcher matcher(0,5);
        matcher.Buy(18510,30).Sell(18450,10);
        matcher.Buy(18500,3).Sell(18460,3);
        matcher.Buy(18490,27) .Sell(18470,20);
        matcher.Buy(18485,10).Sell(18495,20);
        matcher.Buy(18480,4);

        matcher.Match();
		matcher.GenerateItems();
        
		OrderItems sellChance;
		sellChance.push_back(OrderItem(18490,18490,27));
		sellChance.push_back(OrderItem(18485,18485,37));
		sellChance.push_back(OrderItem(18480,18480,41));
		//sellChance.push_back(OrderItem(18470,18470,41));
		sellChance.push_back(OrderItem(18465,18470,60));
		sellChance.push_back(OrderItem(18465,18465,61));
		//sellChance.push_back(OrderItem(18460,18460,61));
		sellChance.push_back(OrderItem(18455,18460,63));
		sellChance.push_back(OrderItem(18455,18455,64));
		//sellChance.push_back(OrderItem(18450,18450,64));
		sellChance.push_back(OrderItem(18445,18450,73));
		sellChance.push_back(OrderItem(18445,18445,74));
        
		EXPECT_EQ(sellChance,matcher.GetSellOrderItems());
		OrderItems const& sellOrderItems = matcher.GetSellOrderItems();
		for (size_t i = 0; i < sellOrderItems.size(); ++i)
		{
			OrderItem const& item = sellOrderItems[i];
			ContractMatcher matcherTest = matcher;
			matcherTest.AddSell(item.orderPrice,item.quantity);
			EXPECT_EQ(item.dealPrice,matcherTest.Match());
		}
	}
}